<script lang="ts" setup>
import type { DictDataInOrUpReq, SysDictDataVO } from '@/api/dictData/dictDataType'
import type { DictTypeInOrUpReq, SysDictTypeVO } from '@/api/dictType/dictTypeType'
import { getDictDataPage, saveDictData } from '@/api/dictData/dictDataApi'
import { getDictTypePage, saveDictType } from '@/api/dictType/dictTypeApi'
import useLayoutStore from '@/store/modules/setting'
import { ElMessage } from 'element-plus'
import { nextTick, onMounted, reactive, ref } from 'vue'

// 使用layout组件小仓库
const layoutStore = useLayoutStore()
// 默认页码
const currentPage = ref<number>(1)
// 默认页行数
const pageSize = ref<number>(10)
// 数据总数
const total = ref<number>(0)
// 定义响应式数据 dictName 收集查询条件
const dictName = ref('')
// 定义响应式数据 dictTypeList 收集查询结果
const dictTypeList = ref<SysDictTypeVO[]>([])
// 定义响应式数据控制抽屉展示或者隐藏
const drawer = ref<boolean>(false)
// 定义响应式数据 drawerTitle 收集抽屉标题
const drawerTitle = ref<string>('')
// dictTypeParam 收集新增或修改字典类型表单数据
const dictTypeParam = reactive<DictTypeInOrUpReq>({
  id: undefined,
  dictType: '',
  status: false,
  dictName: '',
  remark: '',
})
// 获取 operateDictTypeFormRef 组件实例
const operateDictTypeFormRef = ref()
// 定义操作字段类型表单校验规则
const operateDictTypeRules = {
  // 字典类型编码（唯一）
  dictType: [{ required: true, message: '请输入字典类型编码（唯一）', trigger: 'blur' }],
  // 字典类型名称
  dictName: [{ required: true, message: '请输入字典类型名称', trigger: 'blur' }],
  // 字典状态
  status: [{ required: true, message: '请选择字典状态', trigger: 'blur' }],
}
// 定义响应式数据 dictDataDialogVisible 控制字典明细信息对话框显示或者隐藏
const dictDataDialogVisible = ref<boolean>(false)
// 定义响应式数据 dictDataList 收集字典明细信息
const dictDataList = ref<SysDictDataVO[]>([])
// 定义响应式数据 dataTypeNow 用于记录当前操作的字典类型编码
const dataTypeNow = ref<string>('')
// 默认明细表页码
const dictDataCurrentPage = ref<number>(1)
// 默认明细表页行数
const dictDataPageSize = ref<number>(10)
// 明细表数据总数
const dictDataTotal = ref<number>(0)
// 定义响应式数据 dictDataDrawer 控制字典明细信息抽屉显示或者隐藏
const dictDataDrawer = ref<boolean>(false)
// 定义响应式数据 dictDataDrawerTitle 收集字典明细信息抽屉标题
const dictDataDrawerTitle = ref<string>('')
// 获取 operateDictDataFormRef 组件实例
const operateDictDataFormRef = ref()
// 定义 dictDataParamForm 收集字典明细信息表单数据
const dictDataParamForm = reactive<DictDataInOrUpReq>({
  id: undefined,
  dictType: '',
  dictCode: '',
  dictValue: '',
  sortOrder: 0,
  status: false,
  parentId: 0,
  remark: '',
})
// 定义 operateDictDataRules 用于控制字典明细信息表单校验规则
const operateDictDataRules = {
  // 字典类型编码（唯一）
  dictType: [{ required: true, message: '请输入字典类型编码（唯一）', trigger: 'blur' }],
  // 字典项编码
  dictCode: [{ required: true, message: '请输入字典项编码', trigger: 'blur' }],
  // 字典项值（显示名称）
  dictValue: [{ required: true, message: '请输入字典项值（显示名称）', trigger: 'blur' }],
  // 排序号
  sortOrder: [{ required: true, message: '请输入排序号', trigger: 'blur' }],
  // 状态（0正常，1停用）
  status: [{ required: true, message: '请选择状态', trigger: 'blur' }],
}

// 组件挂载
onMounted(() => {
  // 默认当前页是1
  currentPage.value = 1
  // 默认每页10条数据
  pageSize.value = 10
  // 默认用户名是空
  dictName.value = ''
  // 挂载时默认查询用户信息
  getDictTypePageData()
})

async function getDictTypePageData() {
  try {
    // 调用 getDictTypePage 分页查询
    const result: any = await getDictTypePage({
      dictName: dictName.value,
      pageReq: {
        current: currentPage.value,
        size: pageSize.value,
      },
    })
    if (result.success && result.code === 200) {
      // 更新数据
      dictTypeList.value = result.data
      total.value = result.total
    }
  }
  catch (error) {
    // 处理异常
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    // 显示错误消息
    ElMessage({
      message: `查询失败: ${errorMessage || '未知错误'}`,
      type: 'error',
    })
  }
}

// 分页器下拉菜单自定义事件
function handerPageData() {
  getDictTypePageData()
}

// 重置界面
function reset() {
  layoutStore.refresh = !layoutStore.refresh
}

/**
 * 打开抽屉以新增字典类型
 * 1. 显示抽屉并设置标题为“新增字典类型”。
 * 2. 清空字典类型表单参数，重置为默认值。
 * 3. 清除表单的校验信息，确保新增操作时表单状态干净。
 */
function addDictType() {
  // 显示抽屉
  drawer.value = true

  // 设置抽屉标题为“新增字典类型”
  drawerTitle.value = '新增字典类型'

  // 使用 Object.assign() 方法清空字典类型表单参数，重置为默认值
  Object.assign(dictTypeParam, {
    id: undefined,
    dictType: '',
    status: false,
    dictName: '',
    remark: '',
  })

  // 在下一个 DOM 更新周期中清除表单的校验信息
  nextTick(() => {
    operateDictTypeFormRef.value.clearValidate('dictType')
    operateDictTypeFormRef.value.clearValidate('dictName')
    operateDictTypeFormRef.value.clearValidate('status')
  })
}

/**
 * 保存字典类型的操作函数。
 *
 * @description
 * 该函数用于处理字典类型的保存操作，包括表单校验、调用保存接口、处理成功或失败的逻辑，
 * 以及在异常情况下提供错误提示。
 *
 * @returns {Promise<void>} 无返回值，异步执行。
 */
async function onSaveDictType() {
  try {
    // 校验字段类型表单数据，确保输入内容符合要求
    await operateDictTypeFormRef.value.validate()

    // 调用保存接口 saveDictType，传递字典类型参数
    const result: any = await saveDictType(dictTypeParam)

    // 如果保存成功且返回的状态码为200，则执行以下逻辑
    if (result.success && result.code === 200) {
      // 提示用户操作成功
      ElMessage({
        message: '操作成功',
        type: 'success',
      })

      // 关闭抽屉组件
      drawer.value = false

      // 重置分页参数和查询条件
      currentPage.value = 1 // 默认当前页为第一页
      pageSize.value = 10 // 默认每页显示10条数据
      dictName.value = '' // 清空字典名称查询条件

      // 重新加载字典类型分页数据
      getDictTypePageData()
    }
    else {
      // 如果保存失败，提示用户新增失败
      ElMessage({
        message: result.message,
        type: 'error',
      })
    }
  }
  catch (error) {
    // 捕获异常并根据错误类型生成对应的错误信息
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    else {
      errorMessage = '表单校验失败'
    }

    // 提示用户保存失败的具体原因
    ElMessage({
      message: `保存失败: ${errorMessage}`,
      type: 'error',
    })
  }
}

/**
 * 取消保存字典类型的操作。
 *
 * 该函数用于关闭字典类型抽屉并重置抽屉中的表单数据。
 *
 * @function cancelSaveDictType
 * @returns {void} 无返回值。
 */
function cancelSaveDictType() {
  // 关闭字典类型抽屉
  drawer.value = false

  // 重置字典类型参数对象，清空所有字段
  Object.assign(dictTypeParam, {
    id: undefined,
    dictType: '',
    status: false,
    dictName: '',
    remark: '',
  })
}

/**
 * 更新字典类型的操作函数。
 *
 * @param {SysDictTypeVO} row - 包含字典类型信息的对象，用于填充表单数据。
 * @returns {Promise<void>} - 无返回值的异步函数。
 */
async function updateDictType(row: SysDictTypeVO) {
  // 打开数据字典类型操作抽屉
  drawer.value = true

  // 设置抽屉标题为“修改字典类型”
  drawerTitle.value = '修改字典类型'

  // 将传入的字典类型信息赋值到表单参数对象中
  Object.assign(dictTypeParam, row)

  // 在下一个 DOM 更新周期中清除表单的校验信息，确保表单状态干净
  nextTick(() => {
    operateDictTypeFormRef.value.clearValidate('dictType')
    operateDictTypeFormRef.value.clearValidate('dictName')
    operateDictTypeFormRef.value.clearValidate('status')
  })
}

/**
 * 异步获取字典数据分页信息。
 *
 * @param {string} dictDataParam - 字典类型参数，用于指定需要查询的字典类型。
 * @returns {Promise<void>} - 无返回值，函数主要用于更新字典数据列表或处理错误信息。
 */
async function getDictDataPages(dictDataParam: string) {
  try {
    // 调用接口获取字典数据分页信息，传入字典类型和分页参数
    const result: any = await getDictDataPage({
      dictType: dictDataParam,
      pageReq: {
        current: dictDataCurrentPage.value,
        size: dictDataPageSize.value,
      },
    })

    // 如果接口调用成功且返回的状态码为200，则更新字典数据列表
    if (result.success && result.code === 200) {
      // 收集数据
      dictDataList.value = result.data

      // 收集总数
      dictDataTotal.value = result.total
    }
  }
  catch (error) {
    // 捕获异常并根据错误类型生成对应的错误信息
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    else {
      errorMessage = '表单校验失败'
    }

    // 提示用户保存失败的具体原因
    ElMessage({
      message: `保存失败: ${errorMessage}`,
      type: 'error',
    })
  }
}

// 字典明细列表分页器下拉菜单自定义事件
function handerDictDataPageData() {
  getDictDataPages(dataTypeNow.value)
}

/**
 * 显示字典数据的详细信息。
 *
 * @param {SysDictDataVO} row - 当前选中的字典数据行对象，包含字典类型等信息。
 * @returns {void} 无返回值。
 */
function showDictDatas(row: SysDictDataVO) {
  // 设置当前字典类型和分页信息
  dataTypeNow.value = row.dictType
  dictDataCurrentPage.value = 1
  dictDataPageSize.value = 10

  // 调用接口查询字典明细数据
  getDictDataPages(dataTypeNow.value)

  // 打开字典明细信息对话框
  dictDataDialogVisible.value = true
}

/**
 * 打开字典明细信息抽屉并初始化表单状态。
 *
 * @function addDictData
 * @description 该函数用于新增字典明细时，打开抽屉并重置表单数据和校验状态。
 *              主要操作包括设置抽屉标题、清空表单数据、清除表单校验信息。
 *
 * @returns {void} 无返回值。
 */
function addDictData() {
  // 打开字典明细信息抽屉
  dictDataDrawer.value = true

  // 设置抽屉标题为“新增字典明细”
  dictDataDrawerTitle.value = '新增字典明细'

  // 清空字典明细参数对象，确保所有字段恢复到初始状态
  Object.assign(dictDataParamForm, {
    id: undefined,
    dictType: dataTypeNow.value,
    dictCode: '',
    dictValue: '',
    sortOrder: 0,
    status: false,
    parentId: 0,
    remark: '',
  })

  // 在下一个 DOM 更新周期中清除表单的校验信息，确保表单状态干净
  nextTick(() => {
    operateDictDataFormRef.value.clearValidate('dictType')
    operateDictDataFormRef.value.clearValidate('dictCode')
    operateDictDataFormRef.value.clearValidate('dictValue')
    operateDictDataFormRef.value.clearValidate('sortOrder')
    operateDictDataFormRef.value.clearValidate('status')
  })
}

/**
 * 保存字典明细数据的异步函数。
 *
 * @function onSaveDictData
 * @description 该函数用于校验表单数据、保存字典明细数据，并在成功或失败时提供用户反馈。
 *              如果保存成功，会重置分页参数和查询条件，并重新加载字典明细数据。
 *
 * @returns {Promise<void>} 无返回值，但可能抛出异常以供调用方处理。
 */
async function onSaveDictData() {
  try {
    // 校验字段类型表单数据，确保输入内容符合要求
    await operateDictDataFormRef.value.validate()

    // 使用表单数据保存字典明细数据
    const result: any = await saveDictData(dictDataParamForm)
    if (result.success && result.code === 200) {
      // 提示用户操作成功
      ElMessage({
        message: '操作成功',
        type: 'success',
      })

      // 关闭抽屉组件
      dictDataDrawer.value = false

      // 重置分页参数和查询条件
      dictDataCurrentPage.value = 1 // 默认当前页为第一页
      dictDataPageSize.value = 10 // 默认每页显示10条数据
      dataTypeNow.value = '' // 清空字典名称查询条件

      // 调用接口查询字典明细数据
      getDictDataPages(dataTypeNow.value)
    }
  }
  catch (error) {
    // 捕获异常并根据错误类型生成对应的错误信息
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    else {
      errorMessage = '表单校验失败'
    }

    // 提示用户保存失败的具体原因
    ElMessage({
      message: `保存失败: ${errorMessage}`,
      type: 'error',
    })
  }
}

/**
 * 取消保存字典数据操作。
 *
 * 该函数用于关闭数据明细信息抽屉并重置表单数据。
 *
 * @function cancelSaveDictData
 * @returns {void} 无返回值。
 */
function cancelSaveDictData() {
  // 关闭数据明细信息抽屉
  dictDataDrawer.value = false

  // 重置表单数据为初始状态
  Object.assign(dictDataParamForm, {
    id: undefined,
    dictType: '',
    dictCode: '',
    dictValue: '',
    sortOrder: 0,
    status: false,
    parentId: 0,
    remark: '',
  })
}

/**
 * 更新字典明细数据的函数。
 *
 * @param {SysDictDataVO} row - 包含字典明细信息的对象，用于更新表单参数。
 *                             该对象应包含所有需要填充到表单中的字段。
 * @returns {void} - 无返回值。
 */
function updateDictData(row: SysDictDataVO) {
  // 打开字典明细信息抽屉
  dictDataDrawer.value = true

  // 设置抽屉标题为“修改字典明细”
  dictDataDrawerTitle.value = '修改字典明细'

  // 将传入的字典明细信息赋值到表单参数对象中
  Object.assign(dictDataParamForm, row)

  // 在下一个 DOM 更新周期中清除表单的校验信息，确保表单状态干净
  nextTick(() => {
    operateDictDataFormRef.value.clearValidate('dictType')
    operateDictDataFormRef.value.clearValidate('dictCode')
    operateDictDataFormRef.value.clearValidate('dictValue')
    operateDictDataFormRef.value.clearValidate('sortOrder')
    operateDictDataFormRef.value.clearValidate('status')
  })
}
</script>

<template>
  <!-- 查询条件 -->
  <el-card style="height: 75px;">
    <el-form :inline="true" class="form-inline">
      <el-form-item label="字典类型名称">
        <el-input v-model="dictName" placeholder="请输入字典类型名称" />
      </el-form-item>
      <el-form-item>
        <el-button v-hasButton="`btn.dictType.page`" type="primary" icon="Search" @click="getDictTypePageData">
          查询
        </el-button>
        <el-button v-hasButton="`btn.dictType.page`" icon="Refresh" @click="reset">
          重置
        </el-button>
      </el-form-item>
    </el-form>
  </el-card>

  <!-- 查询结果列表 -->
  <el-card style="margin: 10px 0px;">
    <el-button v-hasButton="`btn.dictType.save`" type="primary" icon="Plus" @click="addDictType">
      新增字典类型
    </el-button>
    <el-table style="margin: 10px 0px;" :data="dictTypeList" :border="true">
      <el-table-column type="selection" align="center" width="50px" />
      <el-table-column type="index" label="#" align="center" width="50px" />
      <el-table-column prop="id" label="ID" align="center" />
      <el-table-column prop="dictType" label="字典类型编码" align="center" />
      <el-table-column prop="dictName" label="字典类型名称" align="center" />
      <el-table-column prop="status" label="状态" align="center">
        <template #default="scope">
          <el-switch v-model="scope.row.status" active-text="停用" inactive-text="启用" disabled />
        </template>
      </el-table-column>
      <el-table-column prop="remark" label="备注说明" align="center" />
      <el-table-column prop="createTime" label="创建时间" align="center" />
      <el-table-column prop="creatorName" label="创建人" align="center" />
      <el-table-column prop="modifyTime" label="修改时间" align="center" />
      <el-table-column prop="modifierName" label="修改人" align="center" />
      <el-table-column label="操作" width="300px" align="center">
        <template #default="scope">
          <el-button v-hasButton="`btn.dictType.save`" type="warning" icon="Edit" @click="updateDictType(scope.row)">
            修改
          </el-button>
          <el-button v-hasButton="`btn.dictData.page`" type="primary" icon="Promotion" @click="showDictDatas(scope.row)">
            字典数据
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页器 -->
    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :page-sizes="[10, 20, 30, 40, 50]"
      layout="prev, pager, next, jumper,->, sizes, total"
      :total="total"
      @current-change="getDictTypePageData"
      @size-change="handerPageData"
    />
  </el-card>

  <!-- 字典数据编辑抽屉：完成添加新的字典数据或者更新已有的字典数据 -->
  <el-drawer v-model="drawer">
    <template #header>
      <h4>{{ drawerTitle }}</h4>
    </template>
    <template #default>
      <el-form ref="operateDictTypeFormRef" :model="dictTypeParam" :rules="operateDictTypeRules">
        <el-form-item label="字典类型编码（唯一）" prop="dictType">
          <el-input v-model="dictTypeParam.dictType" placeholder="请输入字典类型编码（唯一）" />
        </el-form-item>
        <el-form-item label="字典类型名称" prop="dictName">
          <el-input v-model="dictTypeParam.dictName" placeholder="请输入字典类型名称" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-switch v-model="dictTypeParam.status" active-text="停用" inactive-text="启用" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="dictTypeParam.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button @click="cancelSaveDictType">
          取消
        </el-button>
        <el-button v-hasButton="`btn.dictType.save`" type="primary" @click="onSaveDictType">
          确定
        </el-button>
      </div>
    </template>
  </el-drawer>

  <!-- 字典明细信息对话框：列表展示字典明细信息 -->
  <el-dialog v-model="dictDataDialogVisible" title="字典明细信息" width="90%">
    <el-button v-hasButton="`btn.dictData.save`" type="primary" icon="Plus" @click="addDictData">
      新增字典明细
    </el-button>
    <el-table style="margin: 10px 0px;" :data="dictDataList" :border="true">
      <el-table-column type="selection" align="center" width="50px" />
      <el-table-column type="index" label="#" align="center" width="50px" />
      <el-table-column prop="id" label="ID" align="center" />
      <el-table-column prop="dictType" label="字典类型编码" align="center" />
      <el-table-column prop="dictCode" label="字典项编码" align="center" />
      <el-table-column prop="dictValue" label="字典项值（显示名称）" align="center" />
      <el-table-column prop="sortOrder" label="排序号" align="center" />
      <el-table-column prop="status" label="状态" align="center">
        <template #default="scope">
          <el-switch v-model="scope.row.status" active-text="停用" inactive-text="启用" disabled />
        </template>
      </el-table-column>
      <el-table-column prop="remark" label="备注说明" align="center" />
      <el-table-column prop="createTime" label="创建时间" align="center" />
      <el-table-column prop="creatorName" label="创建人" align="center" />
      <el-table-column prop="modifyTime" label="修改时间" align="center" />
      <el-table-column prop="modifierName" label="修改人" align="center" />
      <el-table-column label="操作" width="120px" align="center">
        <template #default="scope">
          <el-button v-hasButton="`btn.dictData.save`" type="warning" icon="Edit" @click="updateDictData(scope.row)">
            修改
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页器 -->
    <el-pagination
      v-model:current-page="dictDataCurrentPage"
      v-model:page-size="dictDataPageSize"
      :page-sizes="[10, 20, 30, 40, 50]"
      layout="prev, pager, next, jumper,->, sizes, total"
      :total="dictDataTotal"
      @current-change="getDictDataPages(dataTypeNow)"
      @size-change="handerDictDataPageData"
    />
  </el-dialog>

  <!-- 字典明细数据编辑抽屉：完成添加新的字典明细数据或者更新已有的字典明细数据 -->
  <el-drawer v-model="dictDataDrawer">
    <template #header>
      <h4>{{ dictDataDrawerTitle }}</h4>
    </template>
    <template #default>
      <el-form ref="operateDictDataFormRef" :model="dictDataParamForm" :rules="operateDictDataRules">
        <el-form-item label="字典类型编码（唯一）" prop="dictType">
          <el-input v-model="dictDataParamForm.dictType" placeholder="请输入字典类型编码（唯一）" disabled />
        </el-form-item>
        <el-form-item label="字典项编码" prop="dictCode">
          <el-input v-model="dictDataParamForm.dictCode" placeholder="请输入字典项编码" />
        </el-form-item>
        <el-form-item label="字典项值" prop="dictValue">
          <el-input v-model="dictDataParamForm.dictValue" placeholder="请输入字典项值" />
        </el-form-item>
        <el-form-item label="排序号" prop="sortOrder">
          <el-input v-model="dictDataParamForm.sortOrder" placeholder="请输入排序号" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-switch v-model="dictDataParamForm.status" active-text="停用" inactive-text="启用" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="dictDataParamForm.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button @click="cancelSaveDictData">
          取消
        </el-button>
        <el-button v-hasButton="`btn.dictData.save`" type="primary" @click="onSaveDictData">
          确定
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<style scoped>
.form-inline {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
